CloudWatch Events + LambdaでAWS IoTデバイスシャドウを制御する
ども、大瀧です。
AWS IoT デバイスシャドウは、デバイスの状態を管理するための機能です。デバイスがオフラインになることを見越して、オンラインになったタイミングで遅延反映できるようになっているのが特徴ですね。デバイスシャドウを使うためには、デバイス側ではIoTデバイスSDKを用いるのが定番ですが、管理アプリケーションの実装は割とふわっとしています。 そこで今回は、手軽にデバイスシャドウを制御する方法としてAWS Lambdaのスケジュールジョブ実行をご紹介します。
CloudWatch Events + Lambdaでできること
LambdaからAWS SDKを利用すれば、デバイスシャドウの読み取り/書き込みが可能です。一方、CloudWatch Eventsのスケジュール実行 *1は最短5分からCronライクにLambda関数の定期実行できるので、デバイスシャドウによるデバイスのスケジュール制御ができるわけです。以下のユースケースを思いつきました。
- シャドウでデバイスのオン/オフを管理し、朝8時にオン、夕方6時にオフなどのスケジュール運用
- デモ用途でデバイスの状態を5分間隔でトグル
手順1. AWS IoTデバイスシャドウの構成
まず、AWS IoTで対象のデバイス(Thing)を作成し、[Update shadow]リンクからシャドウを登録します。今回はデモ用にデバイスのLEDを点灯させるので、点灯バターンとしてblinkPattern
をシャドウに定義しました。"red"ならLEDを赤色に点灯、"green"なら緑色に点灯という仕様にします。
{ "desired": { "blinkPattern": "green" }, "reported": { "blinkPattern": "green" } }
AWS IoTの管理画面では、以下のような感じです。
この後のLambdaからの接続のために、エンドポイント(パスはAWS SDKが吸収してくれるのでホスト名のみ)とThing名(今回はbx1-08
)を控えておきます。
手順2. Lambdaの構成
今回はNode.jsで実装し、以下のコードでLambda Functionを定義しました。特に外部ライブラリは利用しないのでManagement Consoleの[Code]タブで記述しました。
console.log('Loading function'); var aws = require('aws-sdk'); var endpoint = 'XXXXXXXXXXXX.iot.ap-northeast-1.amazonaws.com'; var thingName = 'bx1-08'; exports.handler = function(event, context) { // AWS IoT Data APIに接続 var iotdata = new aws.IotData( { endpoint: endpoint } ); // デバイスシャドウを取得 var params = { thingName: thingName }; iotdata.getThingShadow(params, function (err, data) { if (!err) { // シャドウドキュメントから現在の設定を取得 var payload = JSON.parse(data.payload); var currentBlinkPattern = payload.state.desired.blinkPattern; console.log("Current Pattern : " + currentBlinkPattern); // redとgreenをトグルし、シャドウドキュメントに合わせたオブジェクトを生成 if(currentBlinkPattern == 'red') { var desiredBlinkPattern = 'green'; } else { var desiredBlinkPattern = 'red'; } var desiredState = { state: { desired: { blinkPattern: desiredBlinkPattern } } }; // デバイスシャドウを書き込む var params = { thingName: thingName, payload: JSON.stringify(desiredState) }; iotdata.updateThingShadow(params, function (err, data) { if (!err) { context.succeed(); } else { context.fail(err); } }); } else { context.fail(err); } }); };
当たり前ですが、JavascriptだとJSONを楽に扱えるので、シンプルに書くことができました。赤だったら緑に、緑なら赤にとデモ向けの簡単なロジックにしています。
Lambda関数に紐付けるIAMロールは以下のようにマネージドポリシーAWSIoTDataAccess
を設定しました。
かなり緩めの設定なので、必要に応じてカスタムポリシーを定義しResource
で対象のThingを絞っても良いでしょう。以下のドキュメントを参照してください。
関数を定義したら、[Event sources]タブ - [+ Add event source]リンクからイベントソースを追加します。[Event source type]から「Scheduled Event」を選択し、任意のスケジュールを登録します。今回は5分おきにしました。
[Submit]をクリックすれば、設定完了です。
実行できているかは、[Monitoring]タブの[Invocations]で確認できます。ちょっと時間が経っている場合のスクリーンショットですが、1時間に12回実行されているので、5分おきなのがわかりますね。
また、IoTの設定でCloudWatch Logsを有効化しておけば、Lambdaのログの他にAWS IoT側でもログが取れます。UpdateThingShadow
APIがコールされていることがわかりますね。
AWS IoTのThingの画面を見ると、トグルしている様子がわかります。
一人でにコロコロ変わるので、見ていて面白いですw
まとめ
IoTデバイスシャドウにアプローチする例として、Lambdaのスケジュール実行をご紹介しました。Lambdaであれば、スケジュール実行以外にAPI Gatewayの組み合わせも使えるので、外部システムと連携させたいといったケースにも応用できそうですね。
ちなみに、今回のサンプルは今日まで開催のネプコンジャパン2016信和産業様ブースでBLE経由でデバイスを制御するデモで利用しています。興味のある方はぜひご来場ください!
脚注
- 以前のScheduled Event Source ↩